package net.jiastudy.web.config;

import java.lang.reflect.Method;
import java.time.Duration;

import javax.annotation.Resource;

import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import com.alibaba.fastjson.support.spring.GenericFastJsonRedisSerializer;

import net.jiastudy.core.common.CustomRedisCacheManager;

@EnableCaching(proxyTargetClass = true)
@Configuration
@ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties(RedisProperties.class)
public class RedisConfig extends CachingConfigurerSupport {

	@Resource
	private LettuceConnectionFactory lettuceConnectionFactory;

	@Bean
	@Override
	public KeyGenerator keyGenerator() {
		return new KeyGenerator() {
			@Override
			public Object generate(Object target, Method method, Object... params) {
				StringBuffer sb = new StringBuffer();
				sb.append(target.getClass().getName());
				sb.append(method.getName());
				for (Object obj : params) {
					sb.append(obj.toString());
				}
				return sb.toString();
			}
		};
	}
	
	@Bean
    public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        // set key serializer
        StringRedisSerializer serializer = CustomRedisCacheManager.STRING_SERIALIZER;
        // 设置key序列化类，否则key前面会多了一些乱码
        template.setKeySerializer(serializer);
        template.setHashKeySerializer(serializer);

        // fastjson serializer
        GenericFastJsonRedisSerializer fastSerializer = CustomRedisCacheManager.FASTJSON_SERIALIZER;
        template.setValueSerializer(fastSerializer);
        template.setHashValueSerializer(fastSerializer);
        // 如果 KeySerializer 或者 ValueSerializer 没有配置，则对应的 KeySerializer、ValueSerializer 才使用这个 Serializer
        template.setDefaultSerializer(fastSerializer);

        // factory
        template.setConnectionFactory(lettuceConnectionFactory);
        template.afterPropertiesSet();
        return template;
    }
	
	@Bean
    @Override
    public CacheManager cacheManager() {
        // 初始化一个RedisCacheWriter
        RedisCacheWriter cacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(lettuceConnectionFactory);

        // 设置默认过期时间：30 分钟
        RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofMinutes(30))
                // .disableCachingNullValues()
                // 使用注解时的序列化、反序列化
                .serializeKeysWith(CustomRedisCacheManager.STRING_PAIR)
                .serializeValuesWith(CustomRedisCacheManager.FASTJSON_PAIR);

        // Map<String, RedisCacheConfiguration> caches = new HashMap<>();
        // // 缓存配置
        // RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
        //         .entryTtl(Duration.ofSeconds(60))
        //         .disableCachingNullValues()
        //         // .prefixKeysWith("redis.service")
        //         .serializeKeysWith(stringPair)
        //         .serializeValuesWith(fastJsonPair);
        // caches.put("redis.service", config);
        // return new TedisCacheManager(cacheWriter, defaultCacheConfig, caches);

        return new CustomRedisCacheManager(cacheWriter, defaultCacheConfig);
    }
	
	/**
	 * RedisTemplate配置
	 */
//	@Bean
//	public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) {
//		RedisTemplate<String, Object> template = new RedisTemplate<>();
//
//		// 使用fastjson序列化
//		FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<Object>(Object.class);
//		// value值的序列化采用fastJsonRedisSerializer
//		template.setValueSerializer(fastJsonRedisSerializer);
//		template.setHashValueSerializer(fastJsonRedisSerializer);
//		// key的序列化采用StringRedisSerializer
//		template.setKeySerializer(new StringRedisSerializer());
//		template.setHashKeySerializer(new StringRedisSerializer());
//
//		template.setConnectionFactory(lettuceConnectionFactory);
//		return template;
//	}

	// 缓存管理器
//	@Bean
//	public CacheManager cacheManager() {
//		RedisCacheManager.RedisCacheManagerBuilder builder = RedisCacheManager.RedisCacheManagerBuilder
//				.fromConnectionFactory(lettuceConnectionFactory);
//		@SuppressWarnings("serial")
//		Set<String> cacheNames = new HashSet<String>() {
//			{
//				add("codeNameCache");
//			}
//		};
//		builder.initialCacheNames(cacheNames);
//		return builder.build();
//	}

}
